use crate::ui::app::*;
use anyhow::Result;
use ratatui::{
    Frame, Terminal,
    backend::Backend,
    layout::{Constraint, Direction, Layout, Rect},
    style::{Color, Style},
    text::{Line, Span, Text},
    widgets::{Block, Borders, Clear, List, ListItem, Paragraph, Wrap},
};

pub fn render_ui<B: Backend>(terminal: &mut Terminal<B>, app: &AppData) -> Result<()> {
    terminal.draw(|frame| {
        // 创建布局
        let main_chunks = Layout::default()
            .direction(Direction::Vertical)
            .margin(1)
            .constraints([
                Constraint::Length(3), // 标题
                Constraint::Min(0),    // 内容
                Constraint::Length(3), // 状态栏
            ])
            .split(frame.area()); // 使用 area() 代替过时的 size()

        // 标题 - 更新为显示仓库状态
        let repo_status = match &app.current_branch {
            Some(branch) => {
                let status_indicator = if app.has_changes {
                    "* " // 星号表示有未提交的更改
                } else {
                    ""
                };
                format!("Git Tools - Branch: {}{}", status_indicator, branch)
            }
            None => "Git Tools - No repository".to_string(),
        };

        let title = Paragraph::new(repo_status)
            .style(Style::default().fg(Color::Cyan))
            .block(Block::default().borders(Borders::ALL));
        frame.render_widget(title, main_chunks[0]);

        let content_chunks = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([
                Constraint::Percentage(40), // 左侧面板 - 占40%
                Constraint::Percentage(60), // 右侧面板 - 占60%
            ])
            .split(main_chunks[1]);
        // 内容区域 - 根据当前状态渲染不同内容
        match app.ui_state {
            AppState::BranchList => {
                // 左侧显示分支列表
                render_branch_list::<B>(frame, app, content_chunks[0]);
                // 右侧显示选中分支的提交
                render_branch_commits::<B>(frame, app, content_chunks[1]);
            }
            AppState::CommitList => {
                // 左侧显示提交列表
                render_commit_list::<B>(frame, app, content_chunks[0]);
                // 右侧显示选中提交的详细信息
                render_commit_details::<B>(frame, app, content_chunks[1]);
            }
            AppState::MergeList => {
                // 左侧显示可合并的提交列表
                render_merge_list::<B>(frame, app, content_chunks[0]);
                // 右侧显示选中提交的详细信息
                render_commit_details::<B>(frame, app, content_chunks[1]);
            }
            AppState::Dialog => {
                // 当处于对话框状态时，仍然渲染底层内容，但是会被对话框覆盖
                render_branch_list::<B>(frame, app, content_chunks[0]);
                render_branch_commits::<B>(frame, app, content_chunks[1]);
                // 渲染对话框
                if let Some(dialog) = &app.dialog {
                    render_dialog::<B>(frame, dialog, frame.area());
                }
            } // 其他状态...
        }

        // 状态栏 - 显示通知或帮助信息
        let status_text = if let Some(notification) = &app.notification {
            notification.clone()
        } else {
            match app.ui_state {
                AppState::BranchList => "按 q 退出 | 回车 选择 | m 合并 | ↑/↓ 导航".to_string(),
                AppState::MergeList => {
                    "空格 选择/取消 | 回车 确认 | Esc 取消 | ↑/↓ 导航".to_string()
                }
                AppState::CommitList => "按 q 退出 | Esc 返回 | ↑/↓ 导航".to_string(),
                AppState::Dialog => "回车 确认 | Esc 取消 | ↑/↓ 导航".to_string(),
                // 其他状态...
            }
        };

        let status = Paragraph::new(status_text)
            .style(Style::default().fg(Color::White))
            .block(Block::default().borders(Borders::ALL));
        frame.render_widget(status, main_chunks[2]);
    })?;

    Ok(())
}

// 添加渲染合并列表的函数
fn render_merge_list<B: Backend>(frame: &mut Frame, app: &AppData, area: Rect) {
    let title = if let Some(branch) = &app.merge_source_branch {
        format!("Merge from '{}'", branch)
    } else {
        "Merge Commits".to_string()
    };

    let items: Vec<ListItem> = app
        .commits
        .iter()
        .enumerate()
        .map(|(i, commit)| {
            let is_selected = i == app.selected_index;
            let is_commit_selected = app.is_commit_selected(i);

            let mut style = Style::default();
            if is_selected {
                style = style.fg(Color::Yellow);
            }

            let prefix = if is_commit_selected {
                Span::styled("[*] ", Style::default().fg(Color::Green))
            } else {
                Span::styled("[ ] ", Style::default())
            };

            let content = Line::from(vec![
                prefix,
                Span::styled(format!("{:.8}", commit.id), style),
                Span::raw(" - "),
                Span::styled(&commit.message, style),
            ]);

            ListItem::new(content)
        })
        .collect();

    // 计算可见区域能显示的行数
    let list_height = area.height.saturating_sub(2); // 减去边框的高度

    // 创建一个列表，设置其滚动位置以保证选中项可见
    let commits_list = List::new(items)
        .block(Block::default().title(title).borders(Borders::ALL))
        .highlight_style(Style::default().fg(Color::Yellow));

    // 计算滚动位置，确保选中项在视图中可见
    let scroll = calculate_scroll_position(app.selected_index, list_height as usize);

    // 渲染列表，设置滚动位置
    frame.render_stateful_widget(
        commits_list,
        area,
        &mut ratatui::widgets::ListState::default()
            .with_selected(Some(app.selected_index))
            .with_offset(scroll),
    );
}
// 渲染确认对话框
fn render_dialog<B: Backend>(frame: &mut Frame, dialog: &ConfirmDialog, area: Rect) {
    // 计算对话框大小和位置
    let width = std::cmp::min(60, area.width.saturating_sub(10));
    let height = std::cmp::min(
        10 + dialog.options.len() as u16,
        area.height.saturating_sub(10),
    );
    let x = (area.width - width) / 2;
    let y = (area.height - height) / 2;
    let dialog_area = Rect::new(x, y, width, height);

    // 创建文本内容
    let mut text_content = vec![
        Line::from(vec![Span::styled(&dialog.message, Style::default())]),
        Line::from(""),
    ];

    // 添加选项
    for (i, option) in dialog.options.iter().enumerate() {
        let style = if i == dialog.selected_option {
            Style::default().fg(Color::Yellow)
        } else {
            Style::default()
        };

        text_content.push(Line::from(vec![
            if i == dialog.selected_option {
                Span::styled("> ", style)
            } else {
                Span::raw("  ")
            },
            Span::styled(&option.label, style),
        ]));
    }

    // 创建对话框
    let dialog_widget = Paragraph::new(text_content)
        .block(
            Block::default()
                .title(dialog.title.clone())
                .borders(Borders::ALL),
        )
        .wrap(Wrap { trim: true });

    // 使用 clear 先清除对话框区域为背景色
    frame.render_widget(Clear, dialog_area);
    // 然后渲染对话框
    frame.render_widget(dialog_widget, dialog_area);
}
// 渲染分支列表（左侧面板）
fn render_branch_list<B: Backend>(frame: &mut Frame, app: &AppData, area: Rect) {
    let items: Vec<ListItem> = app
        .branches
        .iter()
        .enumerate()
        .map(|(i, branch)| {
            let style = if i == app.selected_index {
                Style::default().fg(Color::Yellow)
            } else {
                Style::default()
            };

            ListItem::new(Line::from(vec![Span::styled(branch, style)]))
        })
        .collect();

    let branches_list =
        List::new(items).block(Block::default().title("Git Branches").borders(Borders::ALL));

    frame.render_widget(branches_list, area);
}

// 渲染分支的提交历史（右侧面板 - 当左侧是分支列表时）
fn render_branch_commits<B: Backend>(frame: &mut Frame, app: &AppData, area: Rect) {
    let items: Vec<ListItem> = app
        .commits
        .iter()
        .map(|commit| {
            let content = Line::from(vec![
                Span::styled(
                    format!("{:.8}", commit.id),
                    Style::default().fg(Color::Green),
                ),
                Span::raw(" - "),
                Span::raw(&commit.time),
                Span::raw(": "),
                Span::styled(&commit.message, Style::default()),
            ]);

            ListItem::new(content)
        })
        .collect();

    // 计算可见区域能显示的行数
    let list_height = area.height.saturating_sub(2); // 减去边框的高度

    // 创建列表
    let branches_list =
        List::new(items).block(Block::default().title("Git Branches").borders(Borders::ALL));

    // 计算滚动位置，确保选中项在视图中可见
    let scroll = calculate_scroll_position(app.selected_index, list_height as usize);

    // 渲染列表，设置滚动位置
    frame.render_stateful_widget(
        branches_list,
        area,
        &mut ratatui::widgets::ListState::default()
            .with_selected(Some(app.selected_index))
            .with_offset(scroll),
    );
}

// 添加一个辅助函数，计算应该滚动到哪个位置以保持选中项可见
fn calculate_scroll_position(selected_index: usize, visible_items: usize) -> usize {
    if visible_items == 0 {
        return 0;
    }

    if selected_index < visible_items - 1 {
        // 如果选中项在上半部分，不需要滚动
        0
    } else {
        // 否则，滚动以使选中项在中间位置
        selected_index.saturating_sub(visible_items - 1)
    }
}

// 渲染提交列表（左侧面板 - 当在提交列表状态时）
fn render_commit_list<B: Backend>(frame: &mut Frame, app: &AppData, area: Rect) {
    let items: Vec<ListItem> = app
        .commits
        .iter()
        .enumerate()
        .map(|(i, commit)| {
            let style = if i == app.selected_index {
                Style::default().fg(Color::Yellow)
            } else {
                Style::default()
            };

            let content = Line::from(vec![
                Span::styled(format!("{:.8}", commit.id), style),
                Span::raw(" - "),
                Span::styled(&commit.message, style),
            ]);

            ListItem::new(content)
        })
        .collect();

    // 计算可见区域能显示的行数
    let list_height = area.height.saturating_sub(2); // 减去边框的高度

    // 创建列表
    let commits_list =
        List::new(items).block(Block::default().title("Commits").borders(Borders::ALL));

    // 计算滚动位置，确保选中项在视图中可见
    let scroll = calculate_scroll_position(app.selected_index, list_height as usize);

    // 渲染列表，设置滚动位置
    frame.render_stateful_widget(
        commits_list,
        area,
        &mut ratatui::widgets::ListState::default()
            .with_selected(Some(app.selected_index))
            .with_offset(scroll),
    );
}

// 渲染提交详细信息（右侧面板 - 当左侧是提交列表时）
fn render_commit_details<B: Backend>(frame: &mut Frame, app: &AppData, area: Rect) {
    if app.commits.is_empty() || app.selected_index >= app.commits.len() {
        let no_commit = Paragraph::new("No commit selected").block(
            Block::default()
                .title("Commit Details")
                .borders(Borders::ALL),
        );
        frame.render_widget(no_commit, area);
        return;
    }

    let commit = &app.commits[app.selected_index];
    // 创建基本信息区域
    let header = Text::from(vec![
        Line::from(vec![
            Span::raw("Commit: "),
            Span::styled(&commit.id, Style::default().fg(Color::Green)),
        ]),
        Line::from(""),
        Line::from(vec![Span::raw("Author: "), Span::raw(&commit.author)]),
        Line::from(vec![Span::raw("Date: "), Span::raw(&commit.time)]),
        Line::from(""),
        Line::from(vec![Span::raw("Message:")]),
    ]);

    let mut area_chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(6),  // 头部信息高度
            Constraint::Min(2),     // 消息内容区域
        ])
        .split(area);

    // 重新划分右侧区域：头部、消息、Diff
    let right_panel_chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(6),  // 新的头部信息高度
            Constraint::Length(4),  // 新的消息内容区域
            Constraint::Min(2),     // 新的diff区域
        ])
        .split(area); // 直接对整个右侧区域 area 进行划分

    // 渲染头部信息
    let header_display = Paragraph::new(header.clone()) // 克隆 header 给这个 Paragraph
        .block(Block::default().title("Commit Info").borders(Borders::ALL))
        .wrap(Wrap { trim: true });
    frame.render_widget(header_display, right_panel_chunks[0]);

    // 渲染提交消息内容
    let message_content = Text::from(commit.message.as_str());
    let message_widget = Paragraph::new(message_content)
        .style(Style::default().fg(Color::Cyan))
        .block(Block::default().title("Message").borders(Borders::ALL)) // 添加标题
        .wrap(Wrap { trim: true });
    frame.render_widget(message_widget, right_panel_chunks[1]);

    // 渲染diff信息
    let diff_widget = if let Some(diff_text) = &app.current_diff {
        let mut lines = Vec::new();
        for line_str in diff_text.lines() {
            if line_str.starts_with("diff --git") || line_str.starts_with("index ") || line_str.starts_with("--- a/") || line_str.starts_with("+++ b/") {
                lines.push(Line::from(Span::styled(line_str, Style::default().fg(Color::Yellow))));
            } else if line_str.starts_with('+') {
                lines.push(Line::from(vec![
                    Span::styled("+ ", Style::default().fg(Color::Green)),
                    Span::styled(
                        line_str.strip_prefix('+').unwrap_or(""), // Safely strip prefix
                        Style::default().fg(Color::Green),
                    ),
                ]));
            } else if line_str.starts_with('-') {
                lines.push(Line::from(vec![
                    Span::styled("- ", Style::default().fg(Color::Red)),
                    Span::styled(
                        line_str.strip_prefix('-').unwrap_or(""), // Safely strip prefix
                        Style::default().fg(Color::Red),
                    ),
                ]));
            } else {
                lines.push(Line::from(Span::raw(line_str)));
            }
        }
        Paragraph::new(Text::from(lines))
            .block(Block::default().title("Changes").borders(Borders::ALL))
            .wrap(Wrap { trim: true })
    } else {
        Paragraph::new(Text::from("Loading diff..."))
            .block(Block::default().title("Changes").borders(Borders::ALL))
            .wrap(Wrap { trim: true })
    };
    frame.render_widget(diff_widget, right_panel_chunks[2]);
}
